from django.db import models
from django.contrib.auth import models as auth_models
from django.template import defaultfilters
import datetime
from tagging import models as tag_models
from tagging import fields as tag_fields
from coolblog import utils

class Category(models.Model):
    name = models.CharField(max_length=20, unique=True)
    count = models.IntegerField(default=0)
    slug = models.SlugField(unique=True, blank=True)

    def __unicode__(self):
        return self.name

    def delete(self, *args, **kwargs):
        # only non-default categories can be removed
        if self.id != 1:
            # move articles to default category
            Article.objects.filter(category=self).update(
                category=Category.default())
            super(Category, self).delete(*args, **kwargs)
            # re-calculate the number of articles in each category
            Category.adjust_count()

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = utils.default_slug()
        super(Category, self).save(*args, **kwargs)

    @classmethod
    def default(self):
        return Category.objects.get(pk=1)

    @classmethod
    def adjust_count(self):
        """
        Reset number of articles for each category.
        """
        for cat in Category.objects.all():
            cat.count = Article.objects.filter(category=cat).count()
            cat.save()

class Article(models.Model):
    class Meta:
        ordering = ['-publish_date']

    title = models.CharField(max_length=50, unique=True)
    content = models.TextField(blank=True)
    publish_date = models.DateTimeField(auto_now_add=True)
    last_modify_date = models.DateTimeField(auto_now=True)
    author = models.ForeignKey(auth_models.User, blank=True)
    category = models.ForeignKey(Category, default=1)
    slug = models.SlugField(unique=True, blank=True)
    tags = tag_fields.TagField()

    def __unicode__(self):
        return self.title

    def save(self, *args, **kwargs):
        creating = not self.id

        # If slug is not specified, take current time as slug.
        if not self.slug:
            self.slug = utils.default_slug()
        super(Article, self).save(*args, **kwargs)
        Category.adjust_count()
        # Increment archive by 1 when creating the article.
        if creating:
            Archive.inc(self.publish_date.year, self.publish_date.month)

    def delete(self, *args, **kwargs):
        super(Article, self).delete(*args, **kwargs)
        Category.adjust_count()
        # Decrement archive by 1 when deleting the article.
        Archive.dec(self.publish_date.year, self.publish_date.month)

    def get_tags(self):
        """
        Get tags of this article.
        """
        return tag_models.Tag.objects.get_for_object(self)

    @classmethod
    def get_all(self):
        """
        Get all available articles.
        """
        return Article.objects.all()

    @classmethod
    def get_recent_list(self):
        """
        Get recent articles.
        """
        return Article.objects.all()[:Blog.instance().recent_count]

class Blog(models.Model):
    name = models.CharField(max_length=50)
    keywords = tag_fields.TagField()
    description = models.CharField(max_length=100, blank=True, default='')
    entries_per_page = models.IntegerField(default=10)
    hide_header = models.BooleanField(default=False)
    recent_count = models.IntegerField(default=5)

    def __unicode__(self):
        return self.name

    @classmethod
    def instance(self):
        return Blog.objects.get(pk=1)

    def get_keywords(self):
        return tag_models.Tag.objects.get_for_object(self)

class Archive(models.Model):
    year = models.IntegerField()
    month = models.IntegerField()
    count = models.IntegerField(default=0)

    def __unicode__(self):
        return datetime.date(self.year, self.month, 1).strftime(
            '%B %Y')

    @classmethod
    def inc(self, y, m):
        archive, created = Archive.objects.get_or_create(
            year=y, month=m)
        archive.count = archive.count + 1
        archive.save()

    @classmethod
    def dec(self, y, m):
        try:
            archive = Archive.objects.get(year=y, month=m)
            archive.count = archive.count - 1
            if archive.count > 0:
                archive.save()
            else:
                Archive.objects.get(year=y, month=m).delete()
        except Archive.DoesNotExist:
            pass
            
